package com.easyexcel.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.easyexcel.core.cellconver.AnnotionCellConvertImpl;
import com.easyexcel.core.cellconver.CellConvert;

public class ExcelHelper {

	public static final String EXCEL_SUFFIX_XLSX = ".xlsx";
	public static final String EXCEL_SUFFIX_XLS = ".xls";

	private static final CellConvert ANNOTION_CELLCONVERT = new AnnotionCellConvertImpl();

	public static <T> List<T> readList(String path, Class<T> clazz) {
		return readList(new File(path), 0, clazz);
	}

	public static <T> List<T> readList(String path, int sheetIndex, Class<T> clazz) {
		return readList(new File(path), sheetIndex, clazz);
	}

	public static <T> List<T> readList(File exceleFile, int sheetIndex, Class<T> clazz) {
		return readList(exceleFile, sheetIndex, ANNOTION_CELLCONVERT, clazz);
	}

	/**
	 * @Title: getDataList
	 * @Description: 获取excel的数据
	 * @author xiaoruihu
	 * @param exceleFile
	 *            必填
	 * @param sheetIndex
	 *            必填
	 * @param convert
	 *            必填
	 * @param clazz
	 *            必填
	 * @return
	 */
	public static <T> List<T> readList(File exceleFile, int sheetIndex, CellConvert convert, Class<T> clazz) {
		InputStream input = null;
		try {
			input = new FileInputStream(exceleFile);
			return readList(input, sheetIndex, convert, clazz);
		} catch (Exception e) {

		} finally {
			try {
				if (input != null)
					input.close();
			} catch (IOException e) {
			}
		}
		return null;
	}

	/**
	 * @param url 
	 * @param sheetIndex
	 * @param clazz
	 * @return
	 */
	public static <T> List<T> readListByUrl(String url, int sheetIndex, Class<T> clazz) {

		InputStream input = null;
		try {
			input = new URL(url).openStream();
			return readList(input, sheetIndex, ANNOTION_CELLCONVERT, clazz);
		} catch (Exception e) {
			throw new RuntimeException("读取url失败", e);
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
				}
			}
		}

	}

	public static <T> List<T> readList(InputStream input, int sheetIndex, CellConvert convert, Class<T> clazz) {
		List<T> dataList = new ArrayList<T>();

		try {
			// FileInputStream fis = new FileInputStream(exceleFile);
			Workbook workbook = WorkbookFactory.create(input);

			Sheet sheet = workbook.getSheetAt(sheetIndex);

			int rowCount = sheet.getLastRowNum();

			if (rowCount == 0) {
				// System.out.println("不存在数据");
				return null;
			}

			Row titleRow = sheet.getRow(0);
			int cellCount = titleRow.getLastCellNum();

			// System.out.println("-------------标题-------------------");
			String[] titles = new String[cellCount];
			for (int i = 0; i < cellCount; i++) {
				// System.out.print(titleRow.getCell(i) + "\t");
				titles[i] = titleRow.getCell(i).toString();
			}

			// System.out.println("--------------内容--------------------" +
			// rowCount);
			for (int i = 1; i < (rowCount + 1); i++) {
				Row contentRow = sheet.getRow(i);
                if(contentRow == null) {
                    break;
                }
				Map<String, Cell> mapCell = new HashMap<String, Cell>();
				for (int j = 0; j < cellCount; j++) {
					// System.out.print(contentRow.getCell(j) + "\t");
					mapCell.put(titles[j], contentRow.getCell(j, Row.RETURN_BLANK_AS_NULL));
				}
				T t = convert.readConvert(mapCell, clazz);
				if (t != null) {
					dataList.add(t);
				}
			}

		} catch (Exception e) {
			throw new RuntimeException("获取Excel数据失败", e);
		}

		return dataList;
	}

	public static <T> void writeList(String path, List<T> dataList, Class<T> clazz) {
		writeList(path, "sheet_" + UUID.randomUUID(), dataList, clazz);
	}

	public static <T> void writeList(String path, String sheetName, List<T> dataList, Class<T> clazz) {
		writeList(new File(path), sheetName, dataList, clazz);
	}

	public static <T> void writeList(File exceleFile, String sheetName, List<T> dataList, Class<T> clazz) {
		writeList(exceleFile, sheetName, ANNOTION_CELLCONVERT, dataList, clazz);
	}

	public static <T> Workbook writeList(File exceleFile, String sheetName, CellConvert convert, List<T> dataList,
			Class<T> clazz) {
		try {
			FileOutputStream fileOut = new FileOutputStream(exceleFile);
			Workbook w = writeList(null, exceleFile.getName(), sheetName, convert, dataList, clazz);
			w.write(fileOut);
			fileOut.close();
			return w;
		} catch (Exception e) {
			throw new RuntimeException("未知错误", e);
		}
	}

	public static <T> Workbook writeListEndWith(String excelEnd, String sheetName, List<T> dataList, Class<T> clazz) {
		return writeList(null, excelEnd, sheetName, ANNOTION_CELLCONVERT, dataList, clazz);
	}

	public static <T> Workbook writeListEndWith(Workbook workbook, String excelEnd, String sheetName, List<T> dataList,
			Class<T> clazz) {
		return writeList(workbook, excelEnd, sheetName, ANNOTION_CELLCONVERT, dataList, clazz);
	}

	public static <T> Workbook writeList(Workbook workbook, String excelName, String sheetName, List<T> dataList,
			Class<T> clazz) {
		return writeList(workbook, excelName, sheetName, ANNOTION_CELLCONVERT, dataList, clazz);
	}

	public static <T> Workbook writeList(Workbook workbook, String excelName, String sheetName, CellConvert convert,
			List<T> dataList, Class<T> clazz) {

		try {
			if (workbook == null) {
				if (excelName.endsWith(EXCEL_SUFFIX_XLSX)) {
					workbook = new XSSFWorkbook();
				} else if (excelName.endsWith(EXCEL_SUFFIX_XLS)) {
					workbook = new HSSFWorkbook();
				} else {
					throw new RuntimeException("不识别的后缀名 , 目前只识别  【.xlsx， .xls】");
				}
			}
			Sheet sheet = workbook.createSheet(sheetName);

			convert.writeConvertHead(clazz, sheet);
			if (dataList != null) {
				convert.writeConvertContent(dataList, clazz, sheet);
			}

			return workbook;
		} catch (Exception e) {
			throw new RuntimeException("写入excel数据失败", e);
		}
	}
}
